﻿using System;
//using System.Timers.Timer;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Box2D.XNA;
using Imagine;

namespace Carmack
{
    public enum eWeaponType  { Shotgun, AssaultRifle, Sniper, SideArm, SubMachineGun  }
    public enum eWeaponClass { Primary, Secondary, Explosive, HeavyWeapon, NoWeapon   }
    
    public class WeaponTag{
        eWeaponClass m_class;
        eWeaponType  m_type;
        public 
        WeaponTag( eWeaponClass cls_, eWeaponType typ_ )
        {
            m_class = cls_;
            m_type  = typ_;
        }
    }

    public class CWeaponAmmo
    {
        uint m_bullets;
        uint m_rounds;
        public CWeaponAmmo() { m_bullets=0; m_rounds=0; }
        public uint TotalBullets() { return m_bullets*m_rounds; }
        public uint Bullets
        {
            get{ return m_bullets;  }
            set{ m_bullets = value; }
        }
        public uint Rounds
        {
            get{ return m_rounds;  }
            set{ m_rounds = value; }
        }
    }

    public class CWeaponParams
    {
        public CGameTimer m_timer;
        public float m_rateOfFire;
        //public float m_counter;
        public uint m_bulletsToFire;
        public uint m_bulletsPerRound;
        public uint m_totalRounds;
        public uint m_maxRounds;
        public bool m_canFire;
        public bool m_reloadRequired;
        public eWeaponClass m_weaponClass;
        public eWeaponType m_identity;

        public CWeaponParams( float rate )
        {
            m_timer = new CGameTimer( 1.0, 0.75 );
            m_rateOfFire = rate;
            m_bulletsToFire = 8;
            m_bulletsPerRound = 8;
            m_maxRounds = 5;
            m_totalRounds = 5;
            m_canFire = true;
            m_reloadRequired = false;
            m_weaponClass = eWeaponClass.Primary;
        }
    }

    public abstract class CWeapon //: GameObject
    {   
        #region Private Members
        public eWeaponType m_identity;
        public AnimatedSprite weaponSprite;
        private Vector2 m_directionWeapon;
        private CGameTimer m_timer;
        private float m_rateOfFire;
        //private float m_counter;
        private uint m_bulletsToFire;    // Bullets Remaining To Be Fired In Current Round
        private uint m_bulletsPerRound;  // You Can Fire Limited Bullets Per Magazine
        private uint m_totalRounds;      // Total Rounds Available
        private uint m_maxRounds;        // Maximum Allowed Rounds
        private eWeaponClass m_weaponClass;
        private bool m_canFire;
        private bool m_reloadRequired;
        #endregion

        #region Properties
        public Vector2 Direction
        {
            get { return m_directionWeapon;  }
            set { m_directionWeapon = value; }
        }

        public eWeaponClass WeaponClass
        {
            get { return m_weaponClass;  }
        }

        public eWeaponType Identity
        {
            get { return m_identity;  }
            set { m_identity = value; }
        }
        
        public float RateOfFire
        {
            get { return m_rateOfFire;       }
            set { m_rateOfFire = value;      }
        }

        public uint Bullets
        {
            get { return m_bulletsToFire;  }
            //set { m_bulletsToFire = value; }
        }

        public uint BulletsPerRound
        {
            get { return m_bulletsPerRound;  }
            //set { m_bulletsPerRound = value; }
        }

        public uint RoundsLeft
        {
            get { return m_totalRounds;  }
            //set { m_totalRounds = value; }
        }

        public uint MaxRounds
        {
            get { return m_maxRounds;  }
            //set { m_maxRounds = value; }
        }

        public bool CanFire
        {
            get { return m_canFire;  }
            //set { m_canFire = value; }
        }
        #endregion

        public CWeapon( string tex )
        {
            weaponSprite = new AnimatedSprite(tex);
            m_timer = new CGameTimer(5.0, 1.25);
            m_rateOfFire = 1.0f;
            //m_counter = 0;
            m_bulletsToFire = 10;
            m_bulletsPerRound = 10;
            m_totalRounds = 3;
            m_maxRounds = 7;
            m_canFire = true;
            m_reloadRequired = false;
        }
        public bool IsReloadRequired() 
        { 
            return m_reloadRequired; 
        }
        public void SetReloadFlag( bool flag_ )
        {
            m_reloadRequired = flag_;
        }
        public bool CanFireBullet( )  
        {
            if (!m_reloadRequired && m_bulletsToFire > 0 && m_timer.IsFree())
            {
                m_canFire = true;
                return true;
            }
            m_canFire = false;
            return false;
        }
        public void Update( GameTime gt_ )         
        { 
            weaponSprite.Update(gt_); 
            m_timer.Update(gt_);
            if ( !m_reloadRequired && m_timer.IsFree() )
            {
                m_canFire = true;
            }
        }
        public void Draw(GameTime gt_) 
        { 
            weaponSprite.Draw(gt_); 
        }
        public bool Reload( )
        {
            if(!IsReloadRequired())
                return false;

            if( m_totalRounds > 0 )
            {
                m_totalRounds -= 1;
                m_bulletsToFire = m_bulletsPerRound;
                m_timer.Stop();
                m_canFire = true;
                SetReloadFlag(false); 
                return true;
            }
            return false;
        }
        public uint AddRounds( uint add_ )
        {
            uint roundsLeft = 0;
            m_totalRounds += add_;
            if (m_totalRounds > m_maxRounds)
            {
                roundsLeft = m_totalRounds - m_maxRounds;
                m_totalRounds = m_maxRounds;
            }
            return roundsLeft;
        }
        public void SubtractRounds( uint sub_ )
        {
            m_totalRounds -= sub_;
            if ( m_totalRounds < 0 )
            {
                m_totalRounds = 0; 
            }
        }
        public void DecrementBullets()
        {
            --m_bulletsToFire;
            if( m_bulletsToFire < 1 )
            {
                SetReloadFlag(true);
            }
        }
        public void DecreaseBullets(uint sub_)
        {
            m_bulletsToFire -= sub_;
            if ( m_bulletsToFire < 1 )
            {
                m_bulletsToFire = 0;
                SetReloadFlag( true );
            }
        }
        public void IncrementBullets()
        {
            ++m_bulletsToFire;
            if( m_bulletsToFire > m_bulletsPerRound )
            {
                m_bulletsToFire = m_bulletsPerRound;
            }
        }
        public void IncreaseBullets(uint add_)
        {
            m_bulletsToFire += add_;
            if( m_bulletsToFire > m_bulletsPerRound )
            {
                m_bulletsToFire = m_bulletsPerRound;
            }
        }
        public virtual void Init(CWeaponParams wParams)
        {
            m_timer = wParams.m_timer;
            m_rateOfFire = wParams.m_rateOfFire;
            //m_counter = wParams.m_counter;
            m_bulletsToFire = wParams.m_bulletsToFire;
            m_bulletsPerRound = wParams.m_bulletsPerRound;
            m_totalRounds = wParams.m_totalRounds;
            m_maxRounds = wParams.m_maxRounds;
            m_canFire = wParams.m_canFire;
            m_reloadRequired = wParams.m_reloadRequired;
            m_weaponClass = wParams.m_weaponClass;
        }
        public virtual bool Fire( )
        {
            if( CanFireBullet( ) )
            {
               DecrementBullets( );
               m_timer.Reset( );
               return true;
            }
            return false;
        }
        public bool RaiseAmmo(uint ammo_)
        {
            if (!IsAmmoFull())
            {
                uint numRounds = ammo_ / BulletsPerRound;
                uint numBullets = ammo_ % BulletsPerRound;
                AddRounds(numRounds);
                IncreaseBullets(numBullets);
                return true;
            }
            return false;
        }
        public bool IsAmmoFull()
        {
            if( RoundsLeft == MaxRounds && Bullets == BulletsPerRound )
                return true;
            return false;
        }
        public uint GetTotalAmmo( CWeaponAmmo ammo )
        {
            return m_bulletsToFire*m_totalRounds;
        }
    }

    /// <summary>
    /// ///////////////////////////////////////////////////////////
    /// </summary>
    public class CRangeWeapon : CWeapon
    {
        // private float m_range;
        public CRangeWeapon(string texture) : base(texture) 
        {

        }
        public override void Init(CWeaponParams wParams) { }
        public override bool Fire() 
        { 
            return base.Fire(); 
        }
    }
}